#include "lex.yy.c"
#include "stdio.h"
#include "stdlib.h"

//#define PROGRAM 16
//#define INICIO 17
//#define PONTO 52
//#define PONTOEVIRGULA 54
//#define ASPECT 30
//#define TYPE 15
//#define ID 10
#define true 1
#define false 0


static int * tokens;
static int pos = 0;
static int length=0;
static int naoAcabouOsTokens = 1;
static int t;
static int status;

void obterNovoToken()
{/*
    if(pos >= length)
    {
        printf("acabou os tokens");
        naoAcabouOsTokens = 0;
    }
    t = tokens[pos];
    ++pos;*/ t = yylex();
}

int opBin()
{
    if(naoAcabouOsTokens)
    {
        if(t == OP_ARITMETICO || t == OP_LOGICO || t == RELOP)
        {
            return true;
        }
        else
        {
            printf("opBin(): token não é aritmético nem lógico");
            return false;
        }
    }
    else
    {
        printf("opBin(): acabou os tokens");
        return false;
    }
}

int expressao2()
{
    if(naoAcabouOsTokens && (t == OP_LOGICO || t == OP_ARITMETICO || t == MENOS || t == RELOP))
    {
        obterNovoToken();
        status = expressao();
        if(status == true)
        {
            return true;
        }
        else
        {
            printf("expressao2(): t != expressao() falhou\n");
            return false;
        }
    }
    else
    {
        //printf("expressao2(): t != OP_LOGICO, OP_ARITMETICO, MENOS,RELOP\n");
        //return false;
        return true;
    }
}



int expressao()
{
    if(naoAcabouOsTokens && (t == MENOS || t == NAO))
    {
        obterNovoToken();
    }
    if(naoAcabouOsTokens && t == ABREPAR)
    {
        obterNovoToken();
        status = expressao();
        if(status == true)
        {
            if(naoAcabouOsTokens && t == FECHAPAR)
            {
                obterNovoToken();
                status = expressao2();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("expressao(): expressao2() falhou\n");
                    return false;
                }
            }
            else
            {
                printf("expressao(): Token != FECHAPAR\n");
                return false;
            }
        }
        else
        {
            printf("expressao(): expressao() falhou\n");
            return false;
        }
    }
    else
    {
        if(naoAcabouOsTokens && t == ID)
        {
            status = elemVariavel();
            if(status == true)
            {
                status = expressao2();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("expressao(): expressao2() falhou\n");
                    return false;
                }
            }
            else
            {
                printf("expressao(): elemVariavel falhou\n");
                return false;
            }
        }
        else
        {
            status = valor();
            if(status == true)
            {
                status = expressao2();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("expressao(): expressao2() falhou\n");
                    return false;
                }
            }
            else
            {
                printf("expressao(): valor() falhou\n");
                return false;
            }
        }
    }
}

int ifFunc()
{
    status = expressao();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == THEN)
        {
            obterNovoToken();
            status = instrucao();
            if(status == true)
            {
                if(naoAcabouOsTokens && t == ELSE)
                {
                    status = instrucao();
                    if(status == true)
                    {
                        return true;                        
                    }
                    else
                    {
                        printf("ifFunc(): falhou no instrucao()do else\n");
                        return false;
                    }
                }
                return true;
            }
            else
            {
                printf("ifFunc(): falhou no instrucao()\n");
                return false;
            }
        }
        else
        {
            printf("ifFunc(): faltou token ELSE\n");
            return false;
        }

    }
    else
    {
        printf("ifFunc(): falhou no expressao()\n");
        return false;
    }
}

int forFunc()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == ATRIBUICAO)
        {
            obterNovoToken();
            status = expressao();
            if(status == true)
            {
                if(naoAcabouOsTokens && (t == TO || t == DOWNTO))
                {
                    obterNovoToken();
                    status = expressao();
                    if(status == true)
                    {
                        if(naoAcabouOsTokens && t == DO)
                        {
                            obterNovoToken();
                            status = instrucao();
                            if(status == true)
                            {
                                return true;
                            }
                            else
                            {
                                printf("forFunc(): falhou instrucao()");
                                return false;
                            }
                        }
                        else
                        {
                            printf("forFunc(): token DO faltou ");
                            return false;
                        }
                    }
                    else
                    {
                        printf("forFunc(): falhou expressao() depois do TO/DOWNTO\n");
                        return false;
                    }
                }
                else
                {
                    printf("forFunc(): token TO/DOWNTO faltou\n");
                    return false;
                }
            }
            else
            {
                printf("forFunc(): falhou expressao()");
                return false;
            }
        }
        else
        {
            printf("forFunc(): nao é token ATRIBUICAO\n");
            return false;
        }
    }
    else
    {
        printf("forFunc(): nao é token ID\n");
        return false;
    }
}

int whileFunc()
{
    status = expressao();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == DO)
        {
            obterNovoToken();
            status = instrucao();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("whileFunc(): instrucao() falhou");
            }
        }
        else
        {
            printf("whileFunc(): t != DO");
            return false;
        }
    }
    else
    {
        printf("whileFunc(): expressao() falhou\n");
        return false;
    }
}


int repeatFunc()
{
    status = instrucao();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == UNTIL)
        {
            obterNovoToken();
            status = expressao();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("whileFunc(): expressao() falhou");
            }
        }
        else
        {
            printf("whileFunc(): t != DO");
            return false;
        }
    }
    else
    {
        printf("whileFunc(): instrucao() falhou\n");
        return false;
    }
}

int caseIns()
{
    status = valor();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == DOISPONTOS)
        {
            obterNovoToken();
            status = instrucao();
            if(status == true)
            {
                if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                {
                    obterNovoToken();
                    status = caseIns();
                    if(status == true)
                    {
                        //FAZER NADA
                    }
                    else
                    {
                        printf("caseIns(): caseIns() falhou\n");
                        return false;
                    }
                }
                return true;
            }
            else
            {
                printf("caseIns(): instrucao() falhou\n");
                return false;
            }
        }
        else
        {
            printf("caseIns(): token != DOISPONTOS\n");
            return false;
        }
    }
    else
    {
        printf("caseIns(): valor() falhou\n");
        return false;
    }
}


int caseFunc()
{
    status = expressao();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == OF)
        {
            obterNovoToken();
            status = valor();
            if(status == true)
            {
                if(naoAcabouOsTokens && t == DOISPONTOS)
                {
                    obterNovoToken();
                    status = instrucao();
                    if(status == true)
                    {
                        if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                        {
                            obterNovoToken();
                            status = caseIns();
                            if(status == true)
                            {
                                //FAZER NADA
                            }
                            else
                            {
                                printf("caseFunc(): caseIns() falhou\n");
                                return false;
                            }
                        }
                        if(naoAcabouOsTokens && t == ELSE)
                        {
                            obterNovoToken();
                            status = instrucao();
                            if(status == true)
                            {
                                //FAZER NADA
                            }
                            else
                            {
                                printf("caseFunc(): instrucao() do else falhou\n");
                                return false;
                            }
                        }
                        if(naoAcabouOsTokens && t == FIM)
                        {
                            obterNovoToken();
                            if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                            {
                                return true;
                            }
                            else
                            {
                                printf("caseFunc(): token != PONTOEVIRGULA\n");
                                return false;
                            }
                        }
                    }
                    else
                    {
                        printf("caseFunc(): instrucao() falhou\n");
                        return false;
                    }
                }
                else
                {
                    printf("caseFunc(): token != DOISPONTOS\n");
                    return false;
                }
            }
            else
            {
                printf("caseFunc(): caseIns() falhou\n");
                return false;
            }
        }
        else
        {
            printf("caseFunc(): token != OF\n");
            return false;
        }
    }
    else
    {
        printf("caseFunc(): expressao() falhou\n");
        return false;
    }
}

int auxParamEntrada()
{
    status = expressao();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == VIRGULA)
        {
            obterNovoToken();
            status = auxParamEntrada();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("auxParamEntrada(): auxParamEntrada() falhou\n");
            }
        }
        else
        {
            return true;
        }
    }
    else
    {
        printf("auxParamEntrada(): expressao() falhou\n");
        return false;
    }
}


int parametrosEntrada()
{
    status = auxParamEntrada();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == FECHAPAR)
        {
            obterNovoToken();
            return true;
        }
        else
        {
            printf("parametrosEntrada(): token != FECHAPAR");
            return false;
        }
    }
    else
    {
        printf("parametrosEntrada(): auxParamEntrada() falhou\n");
        return false;
    }
}

int tios()
{
    if(naoAcabouOsTokens)
    {
        if(t == POINTER)
        {
            obterNovoToken();
            status = tios();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("tios(): tios() falhou\n");
                return false;
            }
        }
        else
        {
            return true;
        }
    }
    else
    {
        printf("tios(): falhou token\n");
        return false;
    }
}

int colEx()
{
    status = expressao();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == FECHACOL)
        {
            obterNovoToken();
            status = tios();
            if(status == true)
            {
                if(naoAcabouOsTokens && t == ABRECOL )
                {
                    status = colEx();
                    if(status == true)
                    {
                        return true;
                    }
                    else
                    {
                        printf("colEx(): colEx() falhou\n");
                        return false;
                    }
                }
                else
                {
                    printf("colEx(): token != ABRECOL\n");
                    return false;
                }
            }
            else
            {
                printf("colEx(): tios() falhou\n");
                return false;
            }
        }
        else
        {
            printf("colEx(): token != FECHACOL\n");
            return false;
        }
    }
    else
    {
        printf("colEx(): expressao() falhou\n");
        return false;
    }
}

int elemVariavel()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == ABREPAR)
        {
            obterNovoToken();
            status = parametrosEntrada();
            if(status == true)
            {
                //FAZER NADA
            }
            else
            {
                printf("elemVariavel(): parametrosEntrada() falhou\n");
                return false;
            }
        }
        status = simu();
        if(status == true)
        {
            return true;
        }
        else
        {
            printf("elemVariavel(): simu() falhou\n");
            return false;
        }
    }
    else
    {
        printf("elemVariavel(): token != ID\n");
        return false;
    }
}


int elemVar()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        status = simu();
        if(status == true)
        {
            return true;
        }
        else
        {
            printf("elemVar(): simu() falhou\n");
            return false;
        }
    }
    else
    {
        printf("elemVar(): token != ID\n");
        return false;
    }
}




int simu()
{
    status = tios();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == ABRECOL)
        {
            obterNovoToken();
            status = colEx();
            if(status == true)
            {
                //FAZER NADA
            }
            else
            {
                printf("simu(): colEx() falhou\n");
            }
        }
        if(naoAcabouOsTokens && t == PONTO )
        {
            obterNovoToken();
            status = elemVar();
            if(status == true)
            {
                //FAZER NADA
            }
            else
            {
                printf("simu(): token != PONTO\n");
            }
        }
        return true;
    }
    else
    {
        printf("simu(): tios() falhou\n");
        return false;
    }
}


int atribuicao()
{
    status = simu();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == ATRIBUICAO)
        {
            obterNovoToken();
            status = expressao();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("atribuicao(): expressao() falhou\n");
                return false;
            }
        }
        else
        {
            printf("atribuicao(): token != ATRIBUICAO\n");
            return false;
        }
    }
    else
    {
        printf("atribuicao(): simu() falhou\n");
        return false;
    }
}

int atribuicaoOuProc()
{
    if(naoAcabouOsTokens && t == ABREPAR)
    {
        obterNovoToken();
        status = parametrosEntrada();
        if(status == true)
        {
            return true;
        }
        else
        {
            printf("atribuicaoOuProc(): parametrosEntrada() falhou\n");
            return false;
        }
    }
    else
    {
        status = atribuicao();
        if(status == true)
        {
            return true;
        }
        else
        {
            printf("atribuicaoOuProc(): atribuicao() falhou\n");
            return false;
        }
    }
}

int instrucao()
{
    if(naoAcabouOsTokens)
    {
        if(t == IF)
        {
            obterNovoToken();
            status = ifFunc();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("instrucao(): falhou no ifFunc()");
                return false;
            }
        }
        else if(t == WHILE)
        {
            obterNovoToken();
            status = whileFunc();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("instrucao(): falhou no whileFunc()");
                return false;
            }
        }
        else if(t == FOR)
        {
            obterNovoToken();
            status == forFunc();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("instrucao(): falhou no forFunc()");
                return false;
            }
        }
        else if(t == REPEAT)
        {
            obterNovoToken();
            status = repeatFunc();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("instrucao(): falhou no repeatFunc()");
                return false;
            }
        }
        else if(t == CASE)
        {
            obterNovoToken();
            status = repeatFunc();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("instrucao(): falhou no repeatFunc()");
                return false;
            }
        }
        else if(t == INICIO)
        {
            obterNovoToken();
            status = bloco();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("instrucao(): falhou no blocos()");
                return false;
            }

        }
        else if (t == READLN || t == WRITELN)
        {
            obterNovoToken();
            if(naoAcabouOsTokens && t == ABREPAR )
            {
                obterNovoToken();
                status = parametrosEntrada();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("instrucao(): falhou no parametrosEntrada()");
                    return false;
                }
            }
            else
            {
                printf("instrucao(): faltou token ABREPAR  ");
                return false;
            }
        }
        else if(t == ID)
        {
            obterNovoToken();
            status = atribuicaoOuProc();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("instrucao(): falhou no atribuicaoOuProc()");
                return false;
            }
        }
        else if(t == PONTOEVIRGULA)
        {
            return true;
        }
    }
    else
    {
        printf("instrucao(): acabou os tokens");
        return false;
    }
}

int secInstrucao()
{
    status = instrucao();
    if(status == true)
    {
        if(t == PONTOEVIRGULA)
        {
            obterNovoToken();
            status = secInstrucao();
            if(status == true)
            {
               //FAZER NADA
            }
            else
            {
                printf("secInstrucao(): falhou no secInstrucao()");
                return false;
            }
        }
        return true;
    }
    else
    {
        printf("secInstrucao(): instrucao() falhou");
        return false;
    }
}


int valor()
{
    if(naoAcabouOsTokens && (t == NUMERO || t == STRING || t == CHAR || t == REAL || t == TRUE || t == FALSE  ))
    {
        obterNovoToken();
        return true;
    }
    else
    {
        printf("valor(): t nao é numero nem string, nem char nem true nem false\n");
        return false;
    }
}

int parametros()
{
    if(naoAcabouOsTokens)
    {
        if(t == PONTOEVIRGULA)
        {
            obterNovoToken();
            if(naoAcabouOsTokens && t == VAR)
            {
                obterNovoToken();
            }
            if(naoAcabouOsTokens && t == ID)
            {
                obterNovoToken();
                if(naoAcabouOsTokens && t == DOISPONTOS)
                {
                    obterNovoToken();
                    status = tipo();
                    if(status == true)
                    {
                        status = parametros();
                        if(status == true)
                        {
                            return true;
                        }
                        else
                        {
                            printf("parametros(): parametros() falhou");
                            return false;
                        }
                    }
                    else
                    {
                        printf("parametros(): tipo() falhou\n");
                        return false;

                    }
                }
                else
                {
                    printf("parametros(): token nao é DOISPONTOS\n");
                    return false;
                }
            }
            else
            {
                printf("parametros(): token nao é ID\n");
                return false;
            }
        }
        else
        {
            return true;
        }
    }
    else
    {
        printf("parametros(): faltou token.");
        return false;
    }

}

int tipo()
{

    if(naoAcabouOsTokens && (t == REAL_TYPE || t == INTEGER || t == CHAR_TYPE || t == BOOLEAN || t == STRING_TYPE || t == ID ))
    {
        obterNovoToken();
        if(naoAcabouOsTokens)
        {
            return true;
        }
        else
        {
            printf("tipo(): Acabou os tokens\n");            
            return false;//Acabou os tokens
        }
    }
    else if (naoAcabouOsTokens && t == ARRAY)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == ABRECOL )
        {
            obterNovoToken();
            if(naoAcabouOsTokens && t == NUMERO)
            {
                obterNovoToken();
                if(naoAcabouOsTokens && t == RANGE)
                {
                    obterNovoToken();
                    if(naoAcabouOsTokens && t == NUMERO)
                    {
                        obterNovoToken();
                        if(naoAcabouOsTokens && t == FECHACOL)
                        {
                            obterNovoToken();
                            if(naoAcabouOsTokens && t == OF)
                            {
                                obterNovoToken();
                                status = tipo();
                                if(status == true)
                                {
                                    return true;
                                }
                                else
                                {
                                    printf("tipo(): tipo() falhou\n");
                                    return false; // Tipo falhou
                                }
                            }
                            else
                            {
                                    printf("tipo(): Token nao é OF\n");
                                return false; //Token nao é OF
                            }
                        }
                        else
                        {
                                    printf("tipo(): Token não é FECHACOL\n");
                            return false; // Token não é FECHACOL
                        }
                    }
                    else
                    {
                                    printf("tipo(): token não é NUMERO\n");
                        return false; //token não é NUMERO
                    }
                }
                else
                {
                                        printf("tipo(): token não é RANGE\n");
                    return false; //token não é RANGE
                }
            }
            else
            {
                                        printf("tipo(): token não é NUMERO\n");
                return false; // Não é NUMERO
            }
        }
        else
        {
                                        printf("tipo(): token não é ABRECOL\n");
            return false; // NÂO é ABRECOl
        }
    }
    else
    {
                                        printf("tipo(): Não é nada definido\n");
        return false; //Não é nada definido
    }
}

int pointerTipo()
{

    if(naoAcabouOsTokens && (t == REAL_TYPE || t == INTEGER || t == CHAR_TYPE || t == BOOLEAN || t == STRING_TYPE || t == ID ))
    {
        obterNovoToken();
        return true;
    }
    else
    {
                                        printf("pointerTipo(): (t == REAL_TYPE || t == INTEGER || t == CHAR_TYPE || t == BOOLEAN || t == STRING_TYPE || t == ID )\n");
        return false;
    }
}

int identifier()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        return true;
    }
    else
    {
        return false;
    }
}

int campoDeclaracao()
{

    if(naoAcabouOsTokens && t == DOISPONTOS)
    {
        obterNovoToken();
        status = tipoSt();
        if(status == true )
        {
            if(naoAcabouOsTokens && t == PONTOEVIRGULA)
            {
                obterNovoToken();
                if(naoAcabouOsTokens && t == ID)
                {
                    obterNovoToken();
                    status = campoDeclaracao();
                    if(status == false)
                    {
                        return false; //CampoDeclaração falhou
                    }
                }
                else
                {
                    return true;
                }
            }
            else
            {
                return false; //Faltou PONTO E VIRGULA
            }
        }
        else
        {
            return false; //TipoSt() falhou
        }
    }
    else
    {
        return false; //Token não é Dois Pontos
    }
}


int tipoSt()
{

    if(naoAcabouOsTokens && t == RECORD)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == ID)
        {
            obterNovoToken();
            status = campoDeclaracao();
            if(status == true)
            {
                //Não faz nada, continua
            }
            else
            {
                return false; //CampoDeclaração falhou
            }
        }
        if(naoAcabouOsTokens && t == FIM)
        {
            obterNovoToken();
            if(naoAcabouOsTokens && t == PONTOEVIRGULA)
            {
                obterNovoToken();
                return true;
            }
            else
            {
                return false; //Faltou Ponto e Virgula
            }
        }
        else
        {
            return false; // token nao é FIM
        }
    }
    else if(naoAcabouOsTokens && t == POINTER)
    {
        obterNovoToken();
        status = pointerTipo();
        if(status == true)
        {
            return true;
        }
        else
        {
            return false; //Deu erro no PointerTipo
        }
    }
    else
    {
        status = tipo();
        if(status == true)
        {
            return true;
        }
        else
        {
            return false; //Falhou em tipo()
        }
    }
}

int secaoDeclaracaoSubProgram()
{
    if(naoAcabouOsTokens && t == CONST)
    {
        obterNovoToken();
        status = constSection();
        if(status == true)
        {
            //Fazer Nada
        }
        else
        {
            printf("secaoDeclaracaoSubProgram(): constSection falhou\n");
            return false;
        }
    }
    if(naoAcabouOsTokens && t == VAR)
    {
        obterNovoToken();
        status = varSection();
        if(status == true)
        {
            //Fazer Nada
        }
        else
        {
            printf("secaoDeclaracaoSubProgram(): varSection falhou\n");
            return false;
        }
    }
    return true;
}

int typeSection()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == ATRIBUICAO)
        {
            obterNovoToken();
            status = tipoSt();
            if(status == true)
            {
                if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                {
                    obterNovoToken();
                    if(naoAcabouOsTokens && t == ID)
                    {
                           status = typeSection();
                           if(status == true)
                           {
                                //FAZER NADA
                           }
                           else
                           {
                        printf("typeSection(): erro no typeSection()\n");
                               return false;
                           }
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                        printf("program(): nao é PONTIVIRGULA\n");
                    return false; //Não é ;
                }
            }
            else
            {
                        printf("program(): nao eh tipoSt()\n");
                return false;//Não é tipoSt
            }
        }
        else
        {
                        printf("program(): Nao eh ATRIBUICAO\n");
            return false;//Não é ATRIBUICAO
        }
    }
    else
    {
                        printf("program(): Nao eh ID\n");
        return false;//Não é ID
    }
}

int varSection()
{

    if(t == ID)
    {
        obterNovoToken();
        if(t == DOISPONTOS)
        {
            obterNovoToken();
            status = tipo();
            if(status == true)
            {
                if(t == PONTOEVIRGULA)
                {
                    obterNovoToken();
                    if(t == ID)
                    {
                        status = varSection();
                        if(status == true)
                        {
                            return true;
                        }
                        else
                        {
                            return false; //ConstSection falhou
                        }
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return false; //Token nao é ;
                }
            }
            else
            {
                return false; //tipo() falhou
            }
        }
        else
        {
            return false; //Token não é DOISPONTOS
        }
    }
    else
    {
        return false; //Token não é ID
    }
}

int constSection()
{

    if(t == ID)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == ATRIBUICAO)
        {
            obterNovoToken();
            status = valor();
            if(status == true)
            {
                if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                {
                    obterNovoToken();
                    if(naoAcabouOsTokens && t == ID)
                    {
                        status = constSection();
                        if(status == true)
                        {
                            return true;
                        }
                        else
                        {
                            return false; //ConstSection falhou
                        }
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return false; //Token nao é ;
                }
            }
            else
            {
                return false; //valor() falhou
            }
        }
        else
        {
            return false; //Token não é ATRIBUICAO
        }
    }
    else
    {
        return false; //Token não é ID
    }
}

int procOrFunc2()
{


    status = secaoDeclaracaoSubProgram();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == INICIO)
        {
            obterNovoToken();
            status = bloco();
            if(status == true)
            {
                return true;
            }
            else
            {
                printf("procOrFunc2: bloco() falhou");
                return false;
            }
        }
        else
        {
            printf("procOrFunc2: token nao é INICIO");
            return false;
        }
    }
    else
    {
        printf("procOrFunc2: secaoDeclaracaoSubProgram falhou");
        return false;
    }
}

int procedure()
{
    status = procOrFunc();
    if(status == true)
    {
        status = procOrFunc2();
        if(status == true)
        {
            return true;
        }
        else
        {
            printf("procedure(): procOrFunc2 falhou");
            return false;
        }
    }
    else
    {
        printf("procedure(): procOrFunc falhou");
        return false;
    }
}

int function()
{
    status = procOrFunc();
    if(status == true)
    {
        if(naoAcabouOsTokens && t == DOISPONTOS)
        {
            obterNovoToken();
            status = tipo();
            if(status == true)
            {
                status = procOrFunc2();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("procedure(): procOrFunc2 falhou\n");
                    return false;
                }
            }
            else
            {
                printf("procedure(): tipo() falhou\n");
                return false;
            }
        }
        else
        {
            printf("procedure(): token não é DOISPONTOS\n");
            return false;
        }
    }
    else
    {
        printf("procedure(): procOrFunc falhou\n");
        return false;
    }
}



int procOrFunc()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == ABREPAR)
        {
            obterNovoToken();
            if(naoAcabouOsTokens && t == VAR)
            {
                obterNovoToken();
                if(naoAcabouOsTokens && t == ID)
                {
                    obterNovoToken();
                    if(naoAcabouOsTokens && t == DOISPONTOS)
                    {
                        obterNovoToken();
                        status = tipo();
                        if(status == true)
                        {
                            status = parametros();
                            if(status == true)
                            {
                                //FAZER NADA
                            }
                            else
                            {
                                printf("procOrFunc(): parametros() falhou");
                                return false;
                            }
                        }
                        else
                        {
                            printf("procOrFunc(): tipo() falhou");
                            return false;
                        }

                    }
                    else
                    {
                            printf("procOrFunc():token nao é DOISPONTOS");
                            return false;
                    }
                }
                else
                {
                    printf("procOrFunc(): token nao é ID");
                    return false;
                }
            }
            else if(naoAcabouOsTokens && t == ID)
            {
                obterNovoToken();
                if(naoAcabouOsTokens && t == DOISPONTOS)
                {
                    obterNovoToken();
                    status = tipo();
                    if(status == true)
                    {
                        if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                        {
                            obterNovoToken();
                            status = parametros();
                            if(status == true)
                            {
                                //FAÇA NADA
                            }
                            else
                            {
                                printf("parametros() falhou");
                                return false; //parametros() falhou
                            }
                        }
                        return true;
                    }
                    else
                    {
                        printf("procOrFunc(): tipo() falhou");
                        return false;
                    }

                }
                else
                {
                        printf("procOrFunc():token nao é DOISPONTOS");
                        return false;
                }
            }
            if(naoAcabouOsTokens && t == FECHAPAR)
            {
                obterNovoToken();
                if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                {
                    obterNovoToken();
                    return true;
                }
                else
                {
                    printf("procOrFunc(): token não é PONTOEVIRGULA\n");
                    return false;
                }
            }
            else
            {
                printf("procOrFunc(): token não é FECHAPAR");
                return false;
            }
        }
        else
        {
            printf("procOrFunc(): token nao é )");
            return false; //token não é (
        }
    }
    else
    {
        return false; //token não é ID
    }
}

int defFuncEproc()
{

    if(naoAcabouOsTokens && t == PROCEDURE)
    {
        obterNovoToken();
        status = procedure();
        if(status == true)
        {
            if(naoAcabouOsTokens && (t == FUNCTION || t == PROCEDURE ))
            {
                status = defFuncEproc();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("defFuncEproc(): defFuncEproc() falhou");
                    return false; //procedure() falhou
                }
            }
            else
            {
                return true;
            }
        }
        else
        {
            printf("defFuncEproc(): procedure() falhou");
            return false; //procOrFunc() falhou
        }
    }
    else if (naoAcabouOsTokens & t == FUNCTION)
    {
        obterNovoToken();
        status = function();
        if(status == true)
        {
            if(naoAcabouOsTokens && (t == FUNCTION || t == PROCEDURE ))
            {
                status = defFuncEproc();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("defFuncEproc(): defFuncEproc() falhou");
                    return false; //procedure() falhou
                }
            }
            else
            {
                return true;
            }
        }
        else
        {
            printf("defFuncEproc(): function() falhou");
            return false; //procOrFunc() falhou
        }
    }
}


int secaoDeclaracao()
{

    if(naoAcabouOsTokens && t == CONST)
    {
        obterNovoToken();
        status = constSection();
        if(status == true)
        {
            //FAZER NADA
        }
        else
        {
            return false;//constSection() falhou
        }
    }
    if(naoAcabouOsTokens && t == VAR)
    {
        obterNovoToken();
        status = varSection();
        if(status == true)
        {
            //FAZER NADA
        }
        else
        {
            return false; //varSection() falhou
        }

    }
    if(naoAcabouOsTokens && (t == FUNCTION || t == PROCEDURE ))
    {
        //obterNovoToken();
        status = defFuncEproc();
        if(status == true)
        {
           return true;
        }
        else
        {
            return false; //procedure() falhou
        }
    }
    return true;
}

int procedureAspect()
{
    if(naoAcabouOsTokens && t == INICIO)
    {
        obterNovoToken();
        status = bloco();
        if(status == true)
        {
            if(naoAcabouOsTokens && t == ID)
            {
                obterNovoToken();
                status = procedureAspect();
                if(status = true)
                {
                    return true;
                }
                else
                {
                    printf("procedureAspect(): procedureAspect() falhou\n");
                    return false;
                }
            }
            else
            {
                return true;
            }
        }
        else
        {
            printf("procedureAspect(): bloco() falhou\n");
            return false;
        }
    }
    else
    {
        printf("procedureAspect(): token != INICIO\n");
        return false;
    }
}

int asBeOrAf()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        if(naoAcabouOsTokens && t == DOISPONTOS)
        {
            obterNovoToken();
            if(naoAcabouOsTokens && t == ID)
            {
                obterNovoToken();
                if(naoAcabouOsTokens && t == PONTOEVIRGULA)
                {
                    obterNovoToken();
                    if(naoAcabouOsTokens && (t == BEFORE || t == AFTER))
                    {
                        obterNovoToken();
                        status = asBeOrAf();
                        if(status == true)
                        {
                            return true;
                        }
                        else
                        {
                            printf("asBeOrAf(): asBeOrAf() falhou\n");
                            return false;
                        }
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    printf("asBeOrAf(): token != PONTOEVIRGULA");
                    return false;
                }
            }
            else
            {
                printf("asBeOrAf(): token != segundo ID");
                return false;
            }
        }
        else
        {
            printf("asBeOrAf(): token != DOISPONTOS");
            return false;
        }
    }
    else
    {
        printf("asBeOrAf(): token != Primeiro ID");
        return false;
    }
}


int aspect()
{
    if(naoAcabouOsTokens && t == ID)
    {
        obterNovoToken();
        status = procedureAspect();
        if(status == true)
        {
            if(naoAcabouOsTokens && (t == BEFORE || t == AFTER))
            {
            	obterNovoToken();
                status = asBeOrAf();
                if(status == true)
                {
                    return true;
                }
                else
                {
                    printf("aspect(): asBeOrAf() falhou\n");
                }
            }
            else
            {
                printf("aspect(): token != BEFORE e de AFTER");
                return false;
            }

        }
        else
        {
            printf("aspect(): procedureAspect() falhou");
            return false;
        }
    }
    else
    {
        printf("aspect(): token != ID");
        return false;
    }
}

int bloco()
{
    if(naoAcabouOsTokens && t == FIM)
    {
        obterNovoToken();
        return true;
    }
    else
    {
        status = secInstrucao();
        if(status == true)
        {
            if(naoAcabouOsTokens && t == FIM)
            {
                obterNovoToken();
                return true;
            }
            else
            {
                printf("bloco(): token FIM faltou");
                return false;
            }
        }
        else
        {
            printf("bloco(): secInstrucao(): falhou");
            return false;
        }
    }
}

int program()
{
    obterNovoToken();

    if(naoAcabouOsTokens && t == PROGRAM)
    {
        obterNovoToken();

        status = identifier();
        if(status > 0)
        {

            if(naoAcabouOsTokens && t == PONTOEVIRGULA)
            {
                obterNovoToken();

                if(naoAcabouOsTokens && t == TYPE)
                {
                    obterNovoToken();
                    status = typeSection();
                    if(status > 0)
                    {
                           //FAÇA NADA
                    }
                    else
                    {
                        printf("program(): erro no typeSection()\n");
                        return false; //Erro no typeSection()
                    }
                }
                status = secaoDeclaracao();
                if(status == true)
                {
                    if(naoAcabouOsTokens && t == ASPECT)
                    {
                        obterNovoToken();
                        status = aspect();
                        if(status > 0)
                        {

                        }
                        else
                        {
                        printf("program(): erro no Aspect()\n");
                            return false; //erro no Aspect()
                        }
                    }
                    if(naoAcabouOsTokens && t == INICIO)
                    {
                        obterNovoToken();
                        status = bloco();
                        if(status == true)
                        {
                            if(t == PONTO && pos == length)
                            {
                                return true; //PARABENS
                            }
                            else
                            {
                                printf("token nao eh PONTO");
                                return false; //token nao eh PONTO
                            }
                        }
                        else
                        {
                            printf("Erro em Bloco()");
                            return false; //Erro em Bloco()
                        }

                    }
                    else
                    {
                        printf("program(): token nao é INICIO");
                        return false; //token nao é INICIO
                    }
                }
                else
                {
                    printf("Erro na secaoDeclaracao()");
                    return 0; //Erro na secaoDeclaracao()
                }
            }
            else
            {
                printf("Não é PONTO E VIRGULA");
                return 0; //Não é PONTO E VIRGULA
            }
        }
        else
        {
            printf("Erro na função identificador()");
            return 0; //Erro na função identificador()
        }
    }
    else
    {
        printf("token nao é PROGRAM");
        return 0; //token nao é PROGRAM
    }
}


int main(int argc, char *argv[])
{
    //        printf("entrou para imprimir");
    //        ++argv,--argc;
    //        if ( argc > 0)
    //                yyin = fopen(argv[0],"r");
    //        else
    //                yyin = stdin;
    //        yylex();
    //
    //        int i = 0;
    //        for(i ; i < tamTabela ; i++)
    //        {
    //            printf("nao entrou aki pq?");
    //            printf("%d",tabelaSimbolos[i].token);
    //        }
    //precisa colocar length=0 la em cima....

    tokens = (int *)malloc(sizeof(int) * 1000);
    ++argv, --argc;
    if (argc > 0)
        yyin = fopen(argv[0], "r");
    else
        yyin = stdin;

//    while (tokens[length]=yylex())
//        length++;

    int z = program();
    printf("Resultado de Z: %d\n",z);
    free(tokens);
}

